import heapq
import time
import traceback
import common.globaldefines
from functools import partial

class MinHeapTimer:
    def __init__(self):
        self.heap = []
        self.counter = 0  # 生成唯一ID，避免exec_time相同时比较回调函数
        self.cancelset = set()

    def addTask(self, delay, callback, args=()):
        """添加定时任务

        :param delay: 延迟时间（秒）
        :param callback: 回调函数
        :param args: 回调函数的参数
        """
        exec_time = time.time() + delay
        unique_id = self.counter
        self.counter += 1
        heapq.heappush(self.heap, (exec_time, unique_id, callback, args))
        return unique_id
    
    def removeTask(self, uniqueid: int):
        self.cancelset.add(uniqueid)

    def check_expired(self):
        """检查并执行所有到期的任务"""
        current_time = time.time()
        while self.heap:
            exec_time, unique_id, callback, args = self.heap[0]
            if exec_time > current_time:
                break
            # 弹出任务并执行
            heapq.heappop(self.heap)
            if unique_id in self.cancelset:
                self.cancelset.remove(unique_id)
                continue
            callback(*args)

class TimerManager(common.globaldefines.ThreadBase):

    def __init__(self):
        super(TimerManager, self).__init__()
        self._timer = MinHeapTimer()

    def frame(self):
        node = self.popFromThread()
        while node:
            src, func = node._val
            curname = common.globaldefines.GetCurrentThreadName()
            if curname != src:
                import application
                application.g_App.pushMessage(src, "TimeoutCallback", func)
            else:
                if func:
                    try:
                        func()
                    except:
                        traceback.print_exc()
            node = self.popFromThread()

    def timeout(self, node: common.globaldefines.ThreadLinkNode):
        self.pushToMainThread((node._src, node._val[1]))

    def threadFrame(self):
        node = self.popFromMainThread()
        while node:
            try:
                delay = node._val[0]
                self._timer.addTask(delay, partial(self.timeout, node))
            except:
                traceback.print_exc()
            node = self.popFromMainThread()
        self._timer.check_expired()

g_TimerMgr = TimerManager()

# 示例用法
if __name__ == "__main__":
    timer = MinHeapTimer()

    # 添加测试任务（时间戳用于验证执行时机）
    timer.add_task(5, lambda: DebugPrint(f"[{time.time():.2f}] 5秒任务"))
    timer.add_task(2, lambda: DebugPrint(f"[{time.time():.2f}] 2秒任务"))
    timer.add_task(3, lambda: DebugPrint(f"[{time.time():.2f}] 3秒任务"))
    timer.add_task(3, lambda: DebugPrint(f"[{time.time():.2f}] 另一个3秒任务"))

    # 主循环（每秒检查多次保证时效性）
    try:
        while True:
            timer.check_expired()
            time.sleep(0.1)  # 控制检查频率
    except KeyboardInterrupt:
        DebugPrint("\n定时器已停止")